<!-- 区域健康度告警分析 -->
<template>
  <div class="ywgzt-container">
    <title-banner :title="'区域健康度告警分析'"></title-banner>
    <div class="content">
      <div class="content-h">
        <div class="map-container">
          <div class="map-title">区域健康度</div>
          <div class="map-city">{{provinceName}}：{{queryParams.cityName}}</div>
          <div id="map" class="map-chart"></div>
        </div>
        <div class="chart-container">
          <div class="line-chart">
            <div class="chart-title">
              <div class="circle"></div>
              {{queryParams.cityName}}健康度趋势（%）
            </div>
            <div class="chart" id="healthLine"></div>
          </div>
          <div class="line-chart">
            <div class="chart-title">
              <div class="circle"></div>
              {{queryParams.cityName}}业务响应耗时趋势（毫秒）
            </div>
            <div class="chart" id="responseLine"></div>
          </div>
          <div class="line-chart">
            <div class="chart-title">
              <div class="circle"></div>
              {{queryParams.cityName}}业务访问量/受理量/告警量趋势
            </div>
            <div class="chart" id="countLine"></div>
          </div>
        </div>
      </div>
      <div class="content-c">
        <div class="chart-title">
          <div class="circle"></div>健康度告警分布趋势图（%）
        </div>
        <div class="chart" id="alarmLine"></div>
      </div>
      <div class="content-f">
        <div class="table-title">
          <div class="table-title-text">
            <div class="circle"></div>历史告警查询
          </div>
          <div class="table-time-box">
            告警时间
            <el-date-picker
              v-model="alarmTimeRange"
              type="datetimerange"
              range-separator="至"
              start-placeholder="开始时间"
              end-placeholder="结束时间"
              :clearable="false"
              class="date-picker"
              :disabled-date="disabledDate"
            ></el-date-picker>
            <el-button type="text" class="white-btn" @click="handlerFormInited">查询</el-button>
            <el-button
              type="text"
              class="white-btn"
              :loading="exportLoading"
              @click="handleExport"
            >导出</el-button>
          </div>
        </div>
        <yd-table
          :formData="extendData"
          :tableConfig="tableConfig"
          :tableData="tableData"
          @sizeChangeHandler="handlerSearch1"
          @currentChangeHandler="handlerSearch1"
          @sortChangeHandler="handlerSearch"
        ></yd-table>
      </div>
    </div>
  </div>
</template>

<script setup name="AlarmAnalysis" lang="tsx">
import TitleBanner from "@/views/ops-workbench/components/TitleBanner/index.vue";
import * as echarts from "echarts";
import axios from "axios";
import { queryMapAreaBusinessStatistics } from "@/api/ops-workbench/index";
import {
  queryAreaDetailTrend,
  queryHealthAlarmTrend,
  queryTodayHistoryData,
  exportHistoryAlarm,
} from "@/api/ops-workbench/area-health/alarmAnalysis";
import { getConfigKey } from '@/api/management/systemManage/systemConfig';
import { provincesZh, city } from "/public/Echart/map/js/area_map";
import { parseTime, downloadFromBlob, formatDate } from "@/utils/common";
import { noDataOption } from "@/utils/chartNoData";
import {
  getLineStyle,
  getAreaStyle,
  getGeo,
  chartResize,
  fillCity,
} from "@/utils/ops-workbench/chartCommon";
import { useRoute, useRouter } from "vue-router";
import { ref, reactive, onMounted, onActivated } from "vue";
import useCurrentInstance from '@/utils/useCurrentInstance';

const route = useRoute();
const router = useRouter();
const { proxy } = useCurrentInstance();

let new_formData: anyObj = {};
// 禁选日期
const disabledDate = (time: Date) => {
  return time.getTime() > Date.now()
}
// 请求参数
let queryParams = reactive<anyObj>({});
// 地图请求参数
let areaQueryTime = reactive<anyObj>({});
let place = "jiangxi";
// 省份名称
const provinceName = ref("");
// 地理位置数据
let geoCoordMap: anyObj;
// 图形对象
type ChartType = {
  map: any;
  healthLine: any;
  responseLine: any;
  countLine: any;
  alarmLine: any;
};
let chart: ChartType = {
  map: null,
  healthLine: null,
  responseLine: null,
  countLine: null,
  alarmLine: null,
};
// 线图样式
const lineChartStyle = reactive(getLineStyle());
// 告警时间参数
const alarmTimeRange = ref<any>([]);
// 表单额外参数
let extendData: anyObj = reactive({});
// 列表配置
let tableConfig = reactive({
  columns: [
    {
      label: "告警时间",
      prop: "cycleTime",
      formatter: (row: anyObj, val: string) => {
        return val ? val.substring(0, 19) : val;
      },
    },
    {
      label: "总访问量",
      prop: "count",
    },
    {
      label: "告警访问量",
      prop: "alarmCount",
      renderXss: (row: anyObj, val: ApiVal) => {
        return <span style="color: #ff9a0c">{val}</span>;
      },
    },
    {
      label: "响应慢访问量",
      prop: "dealTimeAlarmCount",
    },
    {
      label: "失败访问量",
      prop: "failCount",
      renderXss: (row: anyObj, val: ApiVal) => {
        return <span style="color: #ff5d84">{val}</span>;
      },
    },
    {
      label: "失败率",
      prop: "failRate",
      formatter: (row: anyObj, val: ApiVal) => {
        return val !== null ? val + "%" : val;
      },
    },
    {
      label: "健康度",
      prop: "healthRate",
      formatter: (row: anyObj, val: ApiVal) => {
        return val !== null ? val + "%" : val;
      },
    },
    // {
    //   label: "告警类型",
    //   prop: "alarmTypeStr",
    // },
    {
      label: "操作",
      prop: "",
      width: 100,
      operation: [
        {
          text: "告警分析",
          handler: (scope: anyObj) => getAlarmDetail(scope.row),
        },
      ],
    },
  ],
  pagination: {
    pageSize: 10,
    pageNum: 1,
    total: 0,
  },
  loading: true,
  alarmType: true,
});
// 列表数据
let tableData = ref([]);
// 导出按钮
const exportLoading = ref(false);
onActivated(() => {
  queryParams = {...route.query,}
  initParams();
  getConfigKey("sys.project.map").then((response: ApiResponse) => {
    place = response.data;
    provinceName.value = provincesZh(place);
    geoCoordMap = getGeo(place);
    // 初始化图表对象
    initCharts();
    // 添加resize监听器,自适应图表大小
    queryAll();
  });
});


// 初始化请求参数
function initParams() {
  const currentDate = new Date();
  // 请求时间 当天0点至当前
  queryParams.startTime = parseTime(currentDate.getTime(), "{y}-{m}-{d}") + " 00:00:00";
  queryParams.endTime = parseTime(currentDate.getTime(), "{y}-{m}-{d} {h}:{i}:00");
  // 地图数据请求时间为最一小时
  areaQueryTime.startTime = parseTime(currentDate.getTime() - 1000 * 3600, "{y}-{m}-{d} {h}:{i}:00");
  areaQueryTime.endTime = parseTime(currentDate.getTime(), "{y}-{m}-{d} {h}:{i}:00");
}
// 初始化图表
function initCharts() {
  let base = import.meta.env.VITE_APP_ASSETS_BASEURL;
  chart.map = echarts.init(document.getElementById("map")!);
  chart.healthLine = echarts.init(document.getElementById("healthLine")!);
  chart.responseLine = echarts.init(document.getElementById("responseLine")!);
  chart.countLine = echarts.init(document.getElementById("countLine")!);
  chart.alarmLine = echarts.init(document.getElementById("alarmLine")!);
  console.log(chart)
  axios.get(`${base}/Echart/map/json/province/${place}.json`).then(res => {
    console.log(res);
    echarts.registerMap(place, res.data);
  });
}
// 自适应图表大小
function handleChartResize() {
  chartResize(chart);
}
// 请求所有数据
function queryAll() {
  getMapBusiData();
  getAreaDetailTrend();
  getAlarmTrend();
}
// 获取地图数据
function getMapBusiData() {
  queryMapAreaBusinessStatistics({
    startTime: areaQueryTime.startTime,
    endTime: areaQueryTime.endTime,
  }).then((res: ApiResponse) => {
    if (res.code !== 0) {
      proxy.$modal.msgWarning(res.msg);
      return;
    }
    fillCity(res.data, geoCoordMap);
    const mapData: anyObj[] = [];
    res.data.forEach((t: anyObj) => {
      if (t.healthRate === undefined || t.healthRate === null) {
        t.healthRate = "";
      }
      mapData.push({
        name: t.areaName,
        value: t.healthRate == 100 ? Number(t.healthRate) : t.healthRate,
      });
    });
    renderMap(mapData);
  });
}
// 请求区域详情趋势数据
function getAreaDetailTrend() {
  queryAreaDetailTrend({
    startTime: queryParams.startTime,
    endTime: queryParams.endTime,
    areaCode: city(queryParams.cityName),
  }).then((res: ApiResponse) => {
    if (res.code !== 0) {
      proxy.$modal.msgWarning(res.msg);
      return;
    }
    let labelTimeArr: string[] = [],
      healthRateArr: number[] = [],
      responseTimeArr: string[] = [],
      visitArr: number[] = [],
      acceptArr: number[] = [],
      alarmArr: number[] = [];
    res.data.forEach((r: anyObj) => {
      labelTimeArr.push(r.cycleTime.substring(11, 16));
      healthRateArr.push(Number(r.healthRate));
      responseTimeArr.push((r.avgServerResponseTime / 1000).toFixed(0));
      visitArr.push(Number(r.count));
      acceptArr.push(Number(r.completeCount));
      alarmArr.push(Number(r.alarmCount));
    });
    renderLineChart("健康度", "healthLine", labelTimeArr, healthRateArr, "rgb(255,154,12)");
    renderLineChart("响应耗时", "responseLine", labelTimeArr, responseTimeArr, "rgb(30,199,154)");
    let countArr: any[] | null = [];
    if (visitArr.length > 0) {
      countArr.push({
        title: "访问量",
        valueArr: visitArr,
        color: "rgb(43,237,237)",
      });
      if (acceptArr.length > 0) {
        countArr.push({
          title: "受理量",
          valueArr: acceptArr,
          color: "rgb(109,84,242)",
        });
      }
      if (alarmArr.length > 0) {
        countArr.push({
          title: "告警量",
          valueArr: alarmArr,
          color: "rgb(74,152,255)",
        });
      }
    } else {
      countArr = null;
    }
    renderLineChart("访问量/受理量/告警量趋势", "countLine", labelTimeArr, [], "", countArr);
    //图表联动
    echarts.connect([
      chart.healthLine,
      chart.responseLine,
      chart.countLine,
    ]);
    handlerFormInited();
  });
}
// 请求健康度告警分布趋势数据
function getAlarmTrend() {
  queryHealthAlarmTrend({
    startTime: queryParams.startTime,
    endTime: queryParams.endTime,
    areaCode: city(queryParams.cityName),
  }).then((res: ApiResponse) => {
    if (res.code !== 0) {
      proxy.$modal.msgWarning(res.msg);
      return;
    }
    let labelTimeArr: string[] = [],
      alarmArr: number[] = [];
    res.data.forEach((r: anyObj) => {
      labelTimeArr.push(r.cycleTime.substring(11, 16));
      alarmArr.push(Number(r.healthRate));
    });
    renderLineChart("健康度", "alarmLine", labelTimeArr, alarmArr, "rgb(252,86,120)");
  });
}
// 渲染折线图
function renderLineChart(title: string, trendType: string, labelTimeArr: string[], valueArr: any[], seriesColor: string, seriesArr: any = undefined) {
  const chartIns = chart[trendType];
  chartIns.clear();
  if (valueArr.length <= 0 && !seriesArr) {
    noDataOption(chartIns, {
      textStyle: { color: "#fff" },
    });
    return;
  }
  let arrSeries: anyObj[] = [];
  if (seriesArr) {
    seriesArr.forEach((series: anyObj) => {
      arrSeries.push({
        name: series.title,
        data: series.valueArr,
        type: "line",
        symbol: "none",
        itemStyle: {
          color: series.color,
        },
        // 填充区域
        areaStyle: getAreaStyle(series.color).areaStyle,
      });
    });
  }
  chartIns.setOption({
    textStyle: {
      color: "#ffffff",
    },
    // 提示框
    tooltip: {
      trigger: "axis",
    },
    // 图例
    legend: {
      show: seriesArr,
      right: "2%",
      top: "0%",
      textStyle: {
        color: "#ffffff",
      },
    },
    // 坐标系
    grid: {
      x: trendType === "alarmLine" ? 40 : 60,
      x2: 20,
      y: seriesArr ? 20 : 10,
      y2: 20,
    },
    xAxis: {
      data: labelTimeArr,
      ...lineChartStyle.xAxisStyle,
    },
    yAxis: {
      ...lineChartStyle.yAxisStyle,
    },
    series: !seriesArr
      ? [
          {
            name: title,
            data: valueArr,
            type: "line",
            symbol: "none",
            itemStyle: {
              color: seriesColor,
            },
            // 填充区域
            areaStyle: getAreaStyle(seriesColor).areaStyle,
          },
        ]
      : arrSeries,
  });
}
// 渲染地图
function renderMap(mapData: anyObj[]) {
  const convertData = function (data: anyObj[]) {
    let res = [];
    for (let i = 0; i < data.length; i++) {
      let geoCoord = geoCoordMap[data[i].name];
      if (geoCoord) {
        res.push({
          name: data[i].name,
          value: geoCoord.concat(data[i].value),
        });
      }
    }
    return res;
  };
  chart.map.setOption({
    tooltip: {
      trigger: "item",
      formatter: function (params: anyObj) {
        if (params.value >= 0) {
          return params.name + "：" + params.value + "%";
        } else {
          return params.name;
        }
      },
    },
    visualMap: {
      show: true,
      min: 0,
      max: 100,
      calculable: true, //是否展示拖拽手柄
      realtime: true, //拖拽时是否更新
      orient: "horizontal", //展现方式
      left: "15%",
      itemWidth: 10,
      itemHeight: 211,
      text: ["", "健康度（%）"],
      textGap: 20,
      color: ["#2a507d", "#ef4b43"],
      textStyle: {
        color: "#FFFFFF",
      },
    },
    geo: {
      map: place,
      roam: true,
      label: {
        // 显示城市标签
        show: true,
        // 城市字体颜色
        color: "rgb(255, 255, 255)",
      },
      emphasis: {
        label: {
          color: "rgb(255, 255, 255)",
        },
        // 高亮状态样式
        itemStyle: {
          areaColor: "rgba(255, 255, 255, 0.1)",
          shadowOffsetX: 0,
          shadowOffsetY: 0,
          shadowBlur: 20,
          borderWidth: 3,
          shadowColor: "rgba(0, 0, 0, 0.5)",
        },
      },
      itemStyle: {
        // 地图边线颜色
        borderColor: "rgb(0, 255, 255)",
        // 边线宽度
        borderWidth: 1,
        // 地图底色
        color: "#2a507d",
      },
    },
    series: [
      {
        name: 1, //浮动框的标题
        type: "map",
        geoIndex: 0,
        nameProperty: "NAME",
        data: mapData,
      },
      {
        name: "healthRateTip",
        type: "scatter",
        coordinateSystem: "geo",
        symbol: "circle",
        symbolSize: [1, 1],
        tooltip: {
          show: false,
        },
        label: {
          show: true,
          color: "#ffffff",
          fontSize: 12,
          position: "bottom",
          formatter(value: anyObj) {
            if (value.data.value[2] !== "") {
              return value.data.value[2] + "%";
            } else {
              return "";
            }
          },
        },
        emphasis: {
          label: {
            color: "#000000",
          },
        },
        itemStyle: {
          color: "#ffffff",
        },
        // 展示对应城市的健康度数值
        data: convertData(mapData),
        showEffectOn: "render",
        rippleEffect: {
          brushType: "stroke",
        },
        zlevel: 1,
      },
    ],
  });
  // 点击切换查询城市
  chart.map.on("click", (e: anyObj) => {
    queryParams.cityName = e.name;
    // 取消高亮别的城市
    chart.map.dispatchAction({
      type: "downplay",
      seriesIndex: 0,
    });
    // 高亮点击的城市
    chart.map.dispatchAction({
      type: "highlight",
      seriesIndex: 0,
      name: e.name,
    });
    getAreaDetailTrend();
    getAlarmTrend();
  });
  // 高亮跳转带过来的城市
  chart.map.dispatchAction({
    type: "highlight",
    seriesIndex: 0,
    name: queryParams.cityName,
  });
}
function handlerFormInited () {
  tableData.value = [];
  tableConfig.pagination.total = 0;
  tableConfig.pagination.pageNum = 1;
  handlerSearch();
  new_formData.alarmTimeRange = "";
}
// 历史告警查询搜索
function handlerSearch() {
  const formData = extendData;

  tableConfig.loading = true;
  if (alarmTimeRange.value.length == 0) {
    formData.startTime = formatDate(new Date()).substring(0, 10) + " 00:00:00";
    formData.endTime = formatDate(new Date());
    alarmTimeRange.value = [formData.startTime, formData.endTime];
  } else {
    formData.startTime = formatDate(alarmTimeRange.value[0]);
    formData.endTime = formatDate(alarmTimeRange.value[1]);
  }
  formData.areaCode = city(queryParams.cityName);
  if (new_formData.alarmTimeRange == "") {
    new_formData = formData;
  }

  queryTodayHistoryData(formData).then((res: ApiResponse) => {
    tableConfig.loading = false;
    tableData.value = res.data.data;
    tableConfig.pagination.total = res.data.total;
  });
}
function handlerSearch1() {
  tableConfig.loading = true;
  queryTodayHistoryData(new_formData).then((res: ApiResponse) => {
    tableConfig.loading = false;
    tableData.value = res.data.data;
    tableConfig.pagination.total = res.data.total;
  });
}
// 告警分析跳转
function getAlarmDetail(obj: anyObj) {
  router.push({
    path: "/ops-workbench/area-health/alarm-analysis-detail/index",
    query: {
      areaCode: city(queryParams.cityName),
      cycleTime: obj.cycleTime,
      id: obj.id,
    },
  });
}
// 历史告警导出
function handleExport() {
  exportLoading.value = true;
  const d = {
    areaName: queryParams.cityName,
    areaCode: extendData.areaCode,
    startTime: extendData.startTime,
    endTime: extendData.endTime,
  };
  exportHistoryAlarm(d).then((res) => {
    downloadFromBlob(res, "", "历史告警查询总览表" + d.startTime.replace(/\D/g, "") + "-" + d.endTime.replace(/\D/g, "") + ".xlsx").then((o) => {
      exportLoading.value = false;
      if (!o.flag) {
        proxy.$modal.msgWarning(o.msg);
      }
    });
  });
}

handlerFormInited();
</script>

<style rel="stylesheet/scss" lang="scss">
@import "@/styles/ops-workbench/common.scss";
@import "@/styles/ops-workbench/yd-table.scss";
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
@mixin box-back {
  background-color: #2a507d;
  border-radius: 10px;
}
.ywgzt-container {
  width: 100%;
  min-height: calc(100vh) !important;
  .chart-title {
    height: 15%;
    width: 100%;
    display: flex;
    align-items: center;
    font-size: 15px;
    padding-left: 10px;
  }
  .chart {
    height: 85%;
    width: 100%;
  }
  .content-h {
    display: flex;
    height: 615px;
    width: 100%;
    .map-container {
      width: 45%;
      height: 100%;
      .map-title {
        color: #2beded;
        font-size: 15px;
      }
      .map-city {
        margin-top: 3px;
      }
      .map-chart {
        height: 90%;
        width: 100%;
      }
    }
    .chart-container {
      width: 55%;
      height: 100%;
      .line-chart {
        @include box-back;
        height: 32%;
        margin-bottom: 5px;
        padding: 5px;
      }
    }
  }
  .content-c {
    @include box-back;
    width: 100%;
    height: 220px;
    padding: 5px;
    margin-bottom: 10px;
  }
  .content-f {
    @include box-back;
    width: 100%;
    padding: 5px;
    .table-title {
      height: 42px;
      width: 100%;
      padding: 0 10px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      .table-title-text {
        font-size: 15px;
        display: flex;
        align-items: center;
      }
      .table-time-box {
        font-size: 14px;
        display: flex;
        align-items: center;
        .date-picker {
          margin: 0 10px;
          width: 340px;
          height: 26px;
          background-color: rgba(255, 255, 255, 0.1);
          border: none;
          :deep(.el-range-input) {
            background-color: rgba(255, 255, 255, 0);
            color: #ffffff;
          }
          :deep(.el-range-separator) {
            color: #ffffff;
          }
        }
      }
    }
  }
}
:deep(.svg-icon) {
  width: 1.25rem;
}
</style>
